/*
 *    Copyright (c) 2014 Xiang Xu <xuxiang@mail.bnu.edu.cn>
 *
 *    Permission is hereby granted, free of charge, to any person
 *    obtaining a copy of this software and associated documentation
 *    files (the "Software"), to deal in the Software without
 *    restriction, including without limitation the rights to use,
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 *    copies of the Software, and to permit persons to whom the
 *    Software is furnished to do so, subject to the following
 *    conditions:
 *
 *    The above copyright notice and this permission notice shall be
 *    included in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *    OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef FACADE_GRAMMAR_H
#define FACADE_GRAMMAR_H

#include "status.h"
#include "shape_grammar.h"
#include <map>

//! This class describe the shape grammar of the facade.
/*!
The grammar is stored in a xml file. We should use this class to load the grammar.
*/
class FacadeGrammar
{
public:
    FacadeGrammar();
    ~FacadeGrammar();

    //! Load the facade grammar from the json file.
    /*!
    \param configure_file The file name of the json file.
    */
    Status ReadGrammar(std::string& configure_file);

    //! Get the number of terminal shape symbols.
    inline int get_terminal_symbol_size()
    {
        return terminal_symbol_.size();
    }

    //! Get the name of the atom symbol.
    inline std::string get_atom_symbol()
    {
        return atom_symbol_;
    }

    //! Get the names of all the terminal symbols.
    inline std::vector<std::string> get_terminal_symbols()
    {
        return terminal_symbol_;
    }

    //! Get the name of a terminal symbol by index.
    inline std::string get_terminal_symbol(int index)
    {
        return terminal_symbol_[index];
    }

    //! Get the names of all the unterminal symbols.
    inline std::vector<std::string> get_unterminal_symbols()
    {
        return unterminal_symbol_;
    }

    //! Get the number of all the unterminal symbols.
    inline int get_unterminal_symbol_size()
    {
        return unterminal_symbol_.size();
    }

    //! Get the name of a unterminal symbol by index.
    inline std::string get_unterminal_symbol(int index)
    {
        return unterminal_symbol_[index];
    }

    //! Get the number of the grammar rules.
    inline int get_grammar_number()
    {
        return grammar_names_.size();
    }

    //! Get a grammar by index.
    inline ShapeGrammar get_grammar(int index)
    {
        return grammar_set_[index];
    }

    //! Get a symbol's split direction.
    inline int get_symbol_apply_direction(std::string symbol)
    {
        return symbol_apply_direction_.at(symbol);
    }

    //! Get the length of the symbol apply direction map.
    // inline int get_symbol_direction_map_size() { return symbol_apply_direction_.size(); }

    //! Add a state-actions pair.
    // inline void push_back_suitable_actions(std::vector<int> action) {suitable_actions_index_.push_back(action); }

    //! Get a symbol's color.
    std::vector<double> get_symbol_color(std::string symbol);

    //! Get all the actions that is suitable to apply to a state(symbol).
    // std::vector<int> get_suitable_action(const int state) { return suitable_actions_index_[state]; }

    //! Get the index of the terminal symbol
    int get_terminal_symbol_index(std::string name)
    {
        return terminal_symbol_index_.at(name);
    }

    inline bool has_empty_symbol()
    {
        return has_empty_symbol_;
    }
    
private:
    // facade grammar
    std::string atom_symbol_; /*!< name of the atom symbol. */
    std::vector<std::string> terminal_symbol_;		/*!< Name of the terminal symbol. */
    std::vector<std::string> unterminal_symbol_;	/*!< Name of the unterminal symbol.*/
    std::map<std::string, int> terminal_symbol_index_;
    std::vector<std::string> grammar_names_;		/*!< Name of all the grammar rules. */
    std::vector<ShapeGrammar> grammar_set_;			/*!< Grammar rule set. */
    std::map<std::string, int> symbol_apply_direction_;		/*!< Symbol-actions map. */
    std::vector<std::vector<double> > symbol_colors_;			/*!< The colors of all the terminal symbols. */
    std::map<std::string, int> symbol_color_map_;			/*!< symbol-color map. */
    bool has_empty_symbol_;			// whether the grammar has empty symbol(empty symbol can be treat as any symbol)
};


#endif
